//
// Created by chao.li on 2023/11/17.
//

#ifndef SRC_DRAWER_NEWTON_H
#define SRC_DRAWER_NEWTON_H

#include <complex>
#include <functional>

#include "drawer_basic.h"

using complexd = std::complex<double>;
using com_func = std::function<complexd(const complexd&)>;

class drawer_newton
        :public drawer_basic
{
    complexd newton_iter( const com_func& fz, const com_func& dfz,
        const complexd& z0, int iter){
        auto z = z0;
        for (int i = 0; i < iter; ++i) {
            z = z - fz(z) / dfz(z);
        }
        return z;
    }

public:
    int ITER_NUM = 10;
    float COLOR_MAP = 0.2;

    void draw_root(
            const vec2& min,
            const vec2& max,
            const com_func& fz,
            const com_func& dfz)
    {

        for (int x = 0; x < p_img->width; x += 1) {
            for (int y = 0; y < p_img->height; y += 1) {
                auto z0 = complexd(
                        lerp(min.x, max.x, x / double (p_img->width-1)),
                        lerp(min.y, max.y, y / double(p_img->height-1))
                );
                auto z = newton_iter(fz, dfz, z0, ITER_NUM);
                auto delta = pow(abs(fz(z)), COLOR_MAP);
                auto color = lerp({0.2, 1, 0.2}, {0.2, 0.2, 1}, delta);
                draw_point({x, y}, color);
            }
        }
    }
};

#endif //SRC_DRAWER_NEWTON_H
